﻿using System;
using System.Collections.Generic;
using System.Text;
using Osteox.ManagedCv;
using System.Xml.Serialization;
using System.Xml;

namespace WinFormSample
{
    public sealed class SampleProperty
    {
        private static SampleProperty current = new SampleProperty();
        public static SampleProperty Current
        {
            get { return current; }
        }

        private SampleProperty() { }

        private Dictionary<Type, object> dictionary = new Dictionary<Type, object>();

        public T GetProperty<T>() where T : class, new()
        {
            if (!dictionary.ContainsKey(typeof(T)))
            {
                dictionary.Add(typeof(T), new T());
            }
            return dictionary[typeof(T)] as T;
        }

        public void SetProperty<T>(T property)
        {
            if (dictionary.ContainsKey(typeof(T)))
            {
                dictionary[typeof(T)] = property;
            }
            else
            {
                dictionary.Add(typeof(T), property);
            }
        }

        public void Save(string filename)
        {
            using (XmlTextWriter writer = new XmlTextWriter(filename, Encoding.Unicode))
            {
                writer.Formatting = Formatting.Indented;
                writer.WriteStartElement("Settings");
                foreach (KeyValuePair<Type, object> pair in dictionary)
                {
                    writer.WriteStartElement("Filter");
                    writer.WriteStartElement("Key");
                    writer.WriteString(pair.Key.FullName);
                    writer.WriteEndElement();
                    XmlSerializer serializer = new XmlSerializer(pair.Key);
                    serializer.Serialize(writer, pair.Value);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
                writer.Flush();
            }
        }

        public void Load(string filename)
        {
            using (XmlTextReader reader = new XmlTextReader(filename))
            {
                dictionary.Clear();
                while (reader.Read())
                {
                    if (reader.IsStartElement("Filter"))
                    {
                        reader.ReadStartElement("Filter");
                        reader.ReadStartElement("Key");
                        string type = reader.ReadString();
                        reader.ReadEndElement();
                        XmlSerializer serializer = new XmlSerializer(Type.GetType(type));
                        dictionary.Add(Type.GetType(type), serializer.Deserialize(reader));
                        reader.ReadEndElement();
                    }
                }
            }
        }
    }

    public class SmoothFilterProperty
    {
        public SmoothType Type { get; set; }
        public int Size1 { get; set; }
        public int Size2 { get; set; }
        public double Sigma1 { get; set; }
        public double Sigma2 { get; set; }
    }

    public class SobelFilterProperty
    {
        public int XOrder { get; set; }
        public int YOrder { get; set; }
        public ApertureSize ApertureSize { get; set; }
    }

    public class CannyFilterProperty
    {
        public double Threshold1 { get; set; }
        public double Threshold2 { get; set; }
        public ApertureSize ApertureSize { get; set; }
    }

    public class LaplaceFilterProperty
    {
        public ApertureSize ApertureSize { get; set; }
    }

    public class KernelFilterProperty
    {
        public int Cols { get; set; }
        public int Rows { get; set; }
        public int AnchorX { get; set; }
        public int AnchorY { get; set; }
        public ShapeType Shape { get; set; }
    }

    public class MorphologyExFilterProperty : KernelFilterProperty
    {
        public MorphologyMethod Method { get; set; }
        public int Iterations { get; set; }
    }

    public class ThresholdFilterProperty
    {
        public double Threshold { get; set; }
        public double MaxValue { get; set; }
        public ThreshTypeFlag ThresholdType { get; set; }
    }

    public class AdaptiveThresholdFilterProperty
    {
        public double MaxValue { get; set; }
        public ThreshTypeFlag ThresholdType { get; set; }
        public AdaptiveThreshMethod AdaptiveMethod { get; set; }
        public int BlockSize { get; set; }
        public double Param1 { get; set; }
    }

    public class DistanceFilterProperty
    {
        public DistanceType DistanceType { get; set; }
        public DistanceTransformMask MaskSize { get; set; }
    }

    public class ScaleFilterProperty
    {
        public double Scale { get; set; }
        public double Shift { get; set; }
    }
}
